package Timer;

import java.util.PriorityQueue;

/**
 * Created with IntelliJ IDEA
 * Description:自己实现一个定时器——课堂
 * User:34398
 * Date:2024-07-28
 * Time:10:41
 */

class MyTimerTask implements Comparable<MyTimerTask> {//记住传泛型参数

    //表示任务具体执行什么
    private Runnable runnable;

    //毫秒级时间戳
    private long time;

    //构造方法
    public MyTimerTask(Runnable runnable, long delay) {
        this.runnable = runnable;

        //得到一个时间戳，到达这个绝对时间，开始执行任务
        this.time = System.currentTimeMillis() + delay;
    }

    public void run() {
        runnable.run();
    }

    public long getTime() {
        return this.time;
    }

    @Override
    public int compareTo(MyTimerTask o) {

        //此处需要建立小堆
        return (int) (this.time - o.time);
    }
}

class Mytimer {

    private Object object=new Object();

    //用list保存不是一个好的选择，后序执行列表中的任务需要一次遍历每一个元素，然后一一对比，把任务
    //执行完，然后从列表中删除，这时非常耗时间的
//        private List<MyTimerTask> list=new ArrayList<>();

    //优先级队列是一个不错的选择
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    private Object locker = new Object();

    public Mytimer() {
        Thread thread = new Thread(() -> {

            //加锁
            try {
                while (true) {
                    synchronized (locker) {

                        /**把if换成while好一点，避免其他意外唤醒wait，去执行无效的peek*/
                        while (queue.isEmpty()) {
//                        continue;//不继续无意义的占用cpu的循环"线程饿死"
                            locker.wait();
                        }
                        MyTimerTask current = queue.peek();

                        //要执行任务了
                        if (System.currentTimeMillis() >= current.getTime()) {

                            //执行任务
                            current.run();
                            //从队列中删除
                            queue.poll();

                        } else {//暂时不执行任务
                            //设定超时时间
                            locker.wait(current.getTime()-System.currentTimeMillis());
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });

        thread.start();
    }

    public void schedule(Runnable runnable, long delay) {

        //加锁
        synchronized (locker) {
            MyTimerTask myTimerTask = new MyTimerTask(runnable, delay);

            //添加到队列里去
            queue.offer(myTimerTask);
            locker.notify();//进来一个元素，就唤醒线程
        }
    }

}

public class TestMyTimer {
    public static void main(String[] args) {
        Mytimer mytimer = new Mytimer();
        mytimer.schedule(() -> {
            System.out.println("hello 3000");
        }, 3000);

        mytimer.schedule(() -> {
            System.out.println("hello 2000");
        }, 2000);

        mytimer.schedule(() -> {
            System.out.println("hello 1000");
        }, 1000);

        System.out.println("程序开始执行");

    }
}
